Publish the experimental React Native chart host - #11
Conversation
📝 WalkthroughWalkthroughChangesReact Native SVG host
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant App
participant Chart
participant ChartRuntime
participant NativeChartScene
participant NativeChartTooltip
App->>Chart: provide chart definition and options
Chart->>ChartRuntime: create scene and focus state
ChartRuntime->>NativeChartScene: render ChartScene
Chart->>NativeChartTooltip: provide focused points and placement options
NativeChartTooltip-->>Chart: render native tooltip
NativeChartScene-->>App: display SVG chart
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
ed7bcde to
059faf0
Compare
f4bc158 to
81ddc12
Compare
6913ceb to
2fa8bbb
Compare
2fa8bbb to
e14545a
Compare
ab003d6 to
6e66997
Compare
e14545a to
ef21c79
Compare
6e66997 to
952e219
Compare
ef21c79 to
04cad52
Compare
952e219 to
0c743f2
Compare
04cad52 to
b7e4085
Compare
521392c to
a0fb632
Compare
0cd6b8f to
287fdff
Compare
ec4aeb4 to
1d63a11
Compare
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (13)
scripts/check-react-native-types.mjs (1)
27-42: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winOne
@types/d3-arrayImageDataallowlist, two divergent copies. Both gates accept exactly two known strict diagnostics, but they filtertscoutput differently, so they can disagree on the same compiler output. Extract one shared helper, for exampleassertKnownImageDataDiagnostics(output), and call it from both sites.
scripts/check-react-native-types.mjs#L27-L42: replace.filter(Boolean)with theerror TSfilter and call the shared helper.scripts/packed-react-native-consumers.mjs#L293-L306: remove the inline allowlist and call the same shared helper.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/check-react-native-types.mjs` around lines 27 - 42, Extract a shared assertKnownImageDataDiagnostics(output) helper for the `@types/d3-array` ImageData allowlist, preserving the requirement of exactly two matching diagnostics. In scripts/check-react-native-types.mjs:27-42, replace the broad Boolean filtering with the error TS filter and call the helper; in scripts/packed-react-native-consumers.mjs:293-306, remove the duplicated inline allowlist and call the same helper.scripts/check-packed-consumers.mjs (2)
84-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMerge the two summary loops.
bundlesandnativeBundlesare formatted with identical code. Concatenate them and print one loop.♻️ Proposed refactor
console.log('Packed exports, declarations, and runtime gate passed.') console.log('| Consumer | Bytes | Gzip |') console.log('| --- | ---: | ---: |') - for (const bundle of bundles) { - console.log( - `| ${bundle.label} | ${formatBytes(bundle.bytes)} | ${formatBytes(bundle.gzip)} |`, - ) - } - for (const bundle of nativeBundles) { + for (const bundle of [...bundles, ...nativeBundles]) { console.log( `| ${bundle.label} | ${formatBytes(bundle.bytes)} | ${formatBytes(bundle.gzip)} |`, ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/check-packed-consumers.mjs` around lines 84 - 96, Merge the separate summary loops over bundles and nativeBundles into one loop by iterating over their concatenated collection, while preserving the existing table row formatting and output order.
307-323: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winKeep native declaration checks enabled with an explicit allowlist.
skipLibCheck: truedisables.d.tserror reporting only for the native@tanstack/react-native-chartsbuild, so declaration regressions inreact-native,react-native-svg, or@types/*may reach public emitted types. Move the native build back toskipLibCheck: falseand constraintypes: []with a small diagnostic allowlist like the@types/d3-arrayhandling elsewhere.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/check-packed-consumers.mjs` around lines 307 - 323, Update the TypeScript options object in the native branch of the consumer check to set skipLibCheck to false and add types: [] so declaration checks remain enabled without implicit ambient packages. Add the smallest explicit diagnostic allowlist for the known native dependency errors, following the existing `@types/d3-array` handling elsewhere in check-packed-consumers.mjs, while preserving the current options for non-native builds.packages/react-native-charts/src/interaction.test.ts (1)
14-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the
sceneOrdernavigation fallback and the remaining focus modes.These tests exercise
focus: 'group-x'and thespatialIndexpath. Two branches ininteraction.tsstay uncovered:
sceneOrderat Lines 147-161. It runs only whenresolveFocusStrategyreturnsundefined, which is the'nearest'mode and the unset mode. No test callsadjacentFocusPointon that navigation order, so the x-then-y-then-index sort is unverified.resolveFocusStrategymappings for'nearest-y'and'group-y'at Lines 136-141.Add a case with
focus: 'nearest'that navigates across the points, and assert the mapping for the two remaining modes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/interaction.test.ts` around lines 14 - 52, Add coverage in interaction.test.ts for the remaining focus behavior: create a model using focus: 'nearest', call adjacentFocusPoint across its navigation order, and assert ordering follows x, then y, then index through the sceneOrder fallback. Also add assertions that resolveFocusStrategy maps 'nearest-y' and 'group-y' to their corresponding strategies, using the existing test helpers and symbols.packages/react-native-charts/src/Chart.tsx (2)
219-225: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winUse the updater form for the pin toggle.
Line 222 reads
pinnedKeyfrom the render closure.activateat Line 255 already uses the updater form for the same toggle. Make both paths consistent so the toggle always reads the committed value.♻️ Proposed change
- if (sticky) setPinnedKey(pinnedKey ? null : (point?.key ?? null)) + if (sticky) { + setPinnedKey((current) => (current ? null : (point?.key ?? null))) + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Chart.tsx` around lines 219 - 225, Update the sticky pin toggle in handleResponderRelease to use the setPinnedKey updater form, matching activate, and derive the next value from the committed previous key while preserving the existing point?.key fallback and null behavior.
136-140: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winDo not write to refs during render.
Assign callbacks to refs inside a
useEffect, or useuseEffectEventfor the latest callbacks. This package targets React^19.2.3, which supportsuseEffectEvent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Chart.tsx` around lines 136 - 140, Update the callback-ref assignments in the Chart component to avoid mutating refs during render: use React’s useEffectEvent for onFocusChange and onFocusGroupChange, or assign their refs inside a useEffect while preserving access to the latest callbacks.packages/react-native-charts/src/Tooltip.tsx (3)
529-543: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
formatValueandchartValueEqualare duplicated across three modules. The package has no shared internal helper module, so each module carries its own copy. The copies can drift, and theDatehandling informatValuealready encodes a date-only heuristic that must stay identical in both locations.
packages/react-native-charts/src/Tooltip.tsx#L529-L543: moveformatValueandchartValueEqualinto a new internal module, for examplesrc/format.ts, and import them here.packages/react-native-charts/src/Chart.tsx#L439-L447: delete the localformatValueand import the shared one.packages/react-native-charts/src/interaction.ts#L201-L205: delete the localchartValueEqualand import the shared one.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Tooltip.tsx` around lines 529 - 543, Extract formatValue and chartValueEqual into a shared internal format module, preserving the existing Date handling exactly, then import them in Tooltip.tsx. Remove the duplicate formatValue from packages/react-native-charts/src/Chart.tsx at lines 439-447 and import the shared helper; remove the duplicate chartValueEqual from packages/react-native-charts/src/interaction.ts at lines 201-205 and import the shared helper.
327-334: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winReplace the argument spread with a single pass over
points.
Math.min(...x)andMath.max(...x)pass one argument per point. A large grouped focus set can exceed the engine argument limit and throw aRangeError. The function also builds two intermediate arrays.
resolveTooltipCoordinatealready computes the same value with a loop at Lines 396-405. Use the same approach here for consistency and safety.♻️ Proposed single-pass bounds
if (anchor === 'group-center') { - const x = points.map((candidate) => candidate.x) - const y = points.map((candidate) => candidate.y) - return { - x: (Math.min(...x) + Math.max(...x)) / 2, - y: (Math.min(...y) + Math.max(...y)) / 2, - } + let minX = point.x + let maxX = point.x + let minY = point.y + let maxY = point.y + for (const candidate of points) { + minX = Math.min(minX, candidate.x) + maxX = Math.max(maxX, candidate.x) + minY = Math.min(minY, candidate.y) + maxY = Math.max(maxY, candidate.y) + } + return { x: (minX + maxX) / 2, y: (minY + maxY) / 2 } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Tooltip.tsx` around lines 327 - 334, Update the group-center branch in resolveTooltipCoordinate to compute x and y bounds in a single pass over points, avoiding the intermediate arrays and Math.min/Math.max argument spreads. Reuse the existing loop-based bounds approach from the later resolveTooltipCoordinate logic, then return the midpoint of the accumulated minima and maxima.
210-262: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winUse the shared tooltip content helper here.
packages/charts-core/src/tooltip.tsowns the default content logic, including axis labels and shared-X content.createNativeTooltipContentduplicates that logic and uses genericformatValuefor every native tooltip instead of reuse through a core helper.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Tooltip.tsx` around lines 210 - 262, Update createNativeTooltipContent to delegate default tooltip generation to the shared tooltip content helper from charts-core, preserving the existing custom content and formatGroup/format handling before delegation. Remove the duplicated shared-X, axis-label, and generic formatting logic plus createTooltipContentContext, and pass the scene, points, and primary point through the core helper so native tooltips use centralized defaults.packages/react-native-charts/src/Chart.test.tsx (2)
122-148: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe assertion does not verify the claim in the test name.
renderToStaticMarkupperforms a single render, soexpect(create).toHaveBeenCalledOnce()only proves that one render callscreateone time. It does not prove that the extension avoids singleton identity across component instances.Render two
Chartinstances with the same extension and assert thatcreatereturns a distinct component for each, or rename the test to state what it checks.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Chart.test.tsx` around lines 122 - 148, Update the test named “creates branded native tooltip extensions without singleton identity” to render two Chart instances using the same customTooltip extension, then assert create is called for both and returns distinct component instances. Alternatively, rename the test to accurately describe the single-render call-count behavior, but preserve the existing extension setup.
15-52: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftEach test file re-invents an incomplete React Native host shim. All three files replace React Native and
react-native-svgprimitives with DOM tags, and each shim is incomplete in a different way. The shared root cause is the absence of one shared host mock, or of the standard React Native test preset.
packages/react-native-charts/src/Chart.test.tsx#L15-L52: extract thisMockViewinto a shared test helper, and forward the dropped propsaccessibilityActions,onAccessibilityAction,onLayout,onStartShouldSetResponder,onResponderGrant,onResponderMove,onResponderRelease,accessibilityLabel,accessibilityValue, andtestID.packages/react-native-charts/src/Tooltip.test.ts#L18-L21: use the shared helper, so theViewmock flattens the arraystyleprop and stops producing React warnings.packages/react-native-charts/src/SvgScene.test.tsx#L8-L48: use the sharedreact-native-svgmock, and assert on the props that the mocked components receive instead of on the serialized DOM attributes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Chart.test.tsx` around lines 15 - 52, Centralize the incomplete React Native host shims into shared test helpers. In packages/react-native-charts/src/Chart.test.tsx:15-52, extract MockView and forward the listed accessibility, responder, layout, and testID props; update packages/react-native-charts/src/Tooltip.test.ts:18-21 to use it for style flattening. In packages/react-native-charts/src/SvgScene.test.tsx:8-48, use the shared react-native-svg mock and assert mocked component props rather than serialized DOM attributes.packages/react-native-charts/src/Tooltip.test.ts (2)
36-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a case for automatic placement selection.
This test pins one explicit placement. It does not cover the
'auto'path, the candidate list ordering, or the overflow comparison loop atTooltip.tsxLines 441-456. That loop selects the placement, so it carries the highest risk inplaceNativeTooltip.Add a case with an anchor near the top edge and
placementset to'auto', then assert that the selected placement flips to'bottom'.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Tooltip.test.ts` around lines 36 - 46, Add a test alongside the existing placeNativeTooltip case that uses an anchor near the top edge and passes 'auto' as the placement, asserting the returned placement is 'bottom'. Ensure the scenario exercises automatic candidate ordering and overflow comparison while preserving the expected clamped coordinates.
237-263: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the shared
ChartScenetest fixture.This
scenehelper duplicates the helper ininteraction.test.tsLines 99-125. Both build the same 100x60 chart with the samecolors,gradients, andthemevalues.SvgScene.test.tsxrepeats most of the same literal.Move one fixture builder into a shared test helper module, so a required new
ChartScenefield needs one update instead of three.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-native-charts/src/Tooltip.test.ts` around lines 237 - 263, Extract the duplicated scene fixture into a shared test-helper module and update Tooltip.test.ts, interaction.test.ts, and SvgScene.test.tsx to reuse it. Preserve the existing 100x60 ChartScene defaults, colors, gradients, and theme values, and ensure the shared builder accepts points while allowing future required ChartScene fields to be updated in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/installation.md`:
- Around line 96-100: Update the support-claim sentence in the installation
documentation to replace “are not yet support claims” with clear wording such as
“are outside the current support claims” or “are not currently supported,” while
preserving the listed platform and capability scope.
- Around line 80-84: Update the bare React Native installation command in the
installation documentation to pin react-native-svg to a version within
`@tanstack/react-native-charts`’ peer range, such as ^15.15.4. Leave the Expo
installation command using expo install unchanged.
In `@packages/react-native-charts/README.md`:
- Around line 19-23: Bound all React Native installation and tested-version
references to the declared peer ranges: in
packages/react-native-charts/README.md lines 19-23 use react-native-svg@^15.15.4
(or the tested exact version), in packages/charts-core/docs/installation.md
lines 20-22 include react@^19.2.3, react-native@^0.86.0, and
react-native-svg@^15.15.4, in packages/charts-core/docs/installation.md lines
82-84 use react-native-svg@^15.15.4, and in
packages/react-native-charts/README.md lines 54-56 replace the 15.15.x reference
with >=15.15.4 <16 or 15.15.5.
In `@packages/react-native-charts/src/Chart.test.tsx`:
- Around line 156-166: Configure the Vitest jsdom test environment to set
globalThis.IS_REACT_ACT_ENVIRONMENT to true before tests run, using the
repository’s existing Vitest setup mechanism. Ensure the setup applies to
Chart.test.tsx and other React tests without changing the React.act usage.
In `@packages/react-native-charts/src/Chart.tsx`:
- Around line 172-183: The restore effect around focusModel.restore must avoid
emitting when the restored point is equivalent to the current focused point: use
samePointIdentity from ./interaction before calling commitFocus, while
preserving the existing reset behavior for failed restores. Update the package
README to state that consumers must memoize the definition prop.
In `@packages/react-native-charts/src/SvgScene.tsx`:
- Around line 270-276: Update sanitizeId and the scopedId flow used by
ChartLinearGradient so arbitrary custom gradient ids remain unique after
SVG-safe normalization; replace the lossy character removal with a
collision-free encoding, or validate and reject ids that would collide before
emitting resources. Preserve stable prefix handling while ensuring distinct
inputs such as a.b, a:b, and ab cannot produce the same SVG identifier.
In `@packages/react-native-charts/src/Tooltip.test.ts`:
- Around line 18-21: Update the react-native mock in Tooltip.test.ts to replace
the string View mapping with a MockView component that flattens array style
props before rendering the div, matching the established MockView behavior in
Chart.test.tsx. Keep the Text mock and existing tooltip rendering behavior
unchanged.
In `@scripts/measure-bundles.mjs`:
- Around line 36-52: Update the bundle grouping in the configuration used by
measure-bundles so charts-core/src/svg-renderer.ts and charts-core/src/svg.ts
are assigned to the neutral/native group rather than browser. Add or use a
dedicated browser-only group for rejecting browser-exclusive modules, while
preserving the universal/native boundary required by
measure-react-native-poc.mjs.
---
Nitpick comments:
In `@packages/react-native-charts/src/Chart.test.tsx`:
- Around line 122-148: Update the test named “creates branded native tooltip
extensions without singleton identity” to render two Chart instances using the
same customTooltip extension, then assert create is called for both and returns
distinct component instances. Alternatively, rename the test to accurately
describe the single-render call-count behavior, but preserve the existing
extension setup.
- Around line 15-52: Centralize the incomplete React Native host shims into
shared test helpers. In packages/react-native-charts/src/Chart.test.tsx:15-52,
extract MockView and forward the listed accessibility, responder, layout, and
testID props; update packages/react-native-charts/src/Tooltip.test.ts:18-21 to
use it for style flattening. In
packages/react-native-charts/src/SvgScene.test.tsx:8-48, use the shared
react-native-svg mock and assert mocked component props rather than serialized
DOM attributes.
In `@packages/react-native-charts/src/Chart.tsx`:
- Around line 219-225: Update the sticky pin toggle in handleResponderRelease to
use the setPinnedKey updater form, matching activate, and derive the next value
from the committed previous key while preserving the existing point?.key
fallback and null behavior.
- Around line 136-140: Update the callback-ref assignments in the Chart
component to avoid mutating refs during render: use React’s useEffectEvent for
onFocusChange and onFocusGroupChange, or assign their refs inside a useEffect
while preserving access to the latest callbacks.
In `@packages/react-native-charts/src/interaction.test.ts`:
- Around line 14-52: Add coverage in interaction.test.ts for the remaining focus
behavior: create a model using focus: 'nearest', call adjacentFocusPoint across
its navigation order, and assert ordering follows x, then y, then index through
the sceneOrder fallback. Also add assertions that resolveFocusStrategy maps
'nearest-y' and 'group-y' to their corresponding strategies, using the existing
test helpers and symbols.
In `@packages/react-native-charts/src/Tooltip.test.ts`:
- Around line 36-46: Add a test alongside the existing placeNativeTooltip case
that uses an anchor near the top edge and passes 'auto' as the placement,
asserting the returned placement is 'bottom'. Ensure the scenario exercises
automatic candidate ordering and overflow comparison while preserving the
expected clamped coordinates.
- Around line 237-263: Extract the duplicated scene fixture into a shared
test-helper module and update Tooltip.test.ts, interaction.test.ts, and
SvgScene.test.tsx to reuse it. Preserve the existing 100x60 ChartScene defaults,
colors, gradients, and theme values, and ensure the shared builder accepts
points while allowing future required ChartScene fields to be updated in one
place.
In `@packages/react-native-charts/src/Tooltip.tsx`:
- Around line 529-543: Extract formatValue and chartValueEqual into a shared
internal format module, preserving the existing Date handling exactly, then
import them in Tooltip.tsx. Remove the duplicate formatValue from
packages/react-native-charts/src/Chart.tsx at lines 439-447 and import the
shared helper; remove the duplicate chartValueEqual from
packages/react-native-charts/src/interaction.ts at lines 201-205 and import the
shared helper.
- Around line 327-334: Update the group-center branch in
resolveTooltipCoordinate to compute x and y bounds in a single pass over points,
avoiding the intermediate arrays and Math.min/Math.max argument spreads. Reuse
the existing loop-based bounds approach from the later resolveTooltipCoordinate
logic, then return the midpoint of the accumulated minima and maxima.
- Around line 210-262: Update createNativeTooltipContent to delegate default
tooltip generation to the shared tooltip content helper from charts-core,
preserving the existing custom content and formatGroup/format handling before
delegation. Remove the duplicated shared-X, axis-label, and generic formatting
logic plus createTooltipContentContext, and pass the scene, points, and primary
point through the core helper so native tooltips use centralized defaults.
In `@scripts/check-packed-consumers.mjs`:
- Around line 84-96: Merge the separate summary loops over bundles and
nativeBundles into one loop by iterating over their concatenated collection,
while preserving the existing table row formatting and output order.
- Around line 307-323: Update the TypeScript options object in the native branch
of the consumer check to set skipLibCheck to false and add types: [] so
declaration checks remain enabled without implicit ambient packages. Add the
smallest explicit diagnostic allowlist for the known native dependency errors,
following the existing `@types/d3-array` handling elsewhere in
check-packed-consumers.mjs, while preserving the current options for non-native
builds.
In `@scripts/check-react-native-types.mjs`:
- Around line 27-42: Extract a shared assertKnownImageDataDiagnostics(output)
helper for the `@types/d3-array` ImageData allowlist, preserving the requirement
of exactly two matching diagnostics. In
scripts/check-react-native-types.mjs:27-42, replace the broad Boolean filtering
with the error TS filter and call the helper; in
scripts/packed-react-native-consumers.mjs:293-306, remove the duplicated inline
allowlist and call the same helper.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 080d04bd-6a0d-48cc-8423-4f698103757d
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (71)
.changeset/README.md.changeset/config.json.changeset/native-svg-host.md.github/workflows/chart-library-benchmarks.yml.gitignoreAPI-FRICTION.mdNATIVE-PLATFORM-SUPPORT-SPIKE.mdREACT-NATIVE-HOST-POC.mdREADME.mdbenchmarks/comparison/bundle-baseline.jsonbenchmarks/entries/charts-react-native-line.tsbenchmarks/entries/charts-react-native-tooltip.tsbenchmarks/entries/charts-react-native.tsdocs/comparison.mddocs/installation.mddocs/overview.mdexamples/charts-expo/App.tsxexamples/charts-expo/app.jsonexamples/charts-expo/index.tsexamples/charts-expo/metro.config.cjsexamples/charts-expo/package.jsonexamples/charts-expo/tsconfig.jsonexamples/charts-react-native/App.granular.tsxexamples/charts-react-native/App.tsxexamples/charts-react-native/RevenueChart.tsxexamples/charts-react-native/app.jsonexamples/charts-react-native/babel.config.cjsexamples/charts-react-native/index.blank.jsexamples/charts-react-native/index.core.jsexamples/charts-react-native/index.granular.jsexamples/charts-react-native/index.jsexamples/charts-react-native/index.svg.jsexamples/charts-react-native/metro.config.cjsexamples/charts-react-native/package.jsonexamples/charts-react-native/tsconfig.jsonexamples/charts-react-native/tsconfig.strict.jsonnx.jsonpackage.jsonpackages/charts-core/docs/comparison.mdpackages/charts-core/docs/installation.mdpackages/charts-core/docs/overview.mdpackages/charts-core/src/reconcile.test.tspackages/react-native-charts/CHANGELOG.mdpackages/react-native-charts/LICENSEpackages/react-native-charts/README.mdpackages/react-native-charts/package.jsonpackages/react-native-charts/src/Chart.test.tsxpackages/react-native-charts/src/Chart.tsxpackages/react-native-charts/src/FocusOverlay.tsxpackages/react-native-charts/src/SvgScene.test.tsxpackages/react-native-charts/src/SvgScene.tsxpackages/react-native-charts/src/Tooltip.test.tspackages/react-native-charts/src/Tooltip.tsxpackages/react-native-charts/src/index.native.tspackages/react-native-charts/src/index.tspackages/react-native-charts/src/interaction.test.tspackages/react-native-charts/src/interaction.tspackages/react-native-charts/src/paint.test.tspackages/react-native-charts/src/paint.tspackages/react-native-charts/src/tooltip-entry.native.tspackages/react-native-charts/src/tooltip-entry.tspackages/react-native-charts/tsconfig.jsonscripts/check-packed-consumers.mjsscripts/check-react-native-types.mjsscripts/docs-contract.mjsscripts/measure-bundles.mjsscripts/measure-react-native-poc.mjsscripts/packed-react-native-consumers.mjsscripts/release-package-config.mjsscripts/release-workflow.test.mjsscripts/sync-release-version.mjs
| Bare React Native 0.86 applications install the renderer directly: | ||
|
|
||
| ```sh | ||
| pnpm add @tanstack/charts @tanstack/react-native-charts d3-scale react-native-svg | ||
| ``` |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
jq -r '.peerDependencies["react-native-svg"]' packages/react-native-charts/package.json
rg -n -C 2 'react-native-svg' docs/installation.md examples/charts-react-native/package.json examples/charts-expo/package.json
printf 'Unqualified registry version: '
pnpm view react-native-svg versionRepository: TanStack/charts
Length of output: 2855
Pin react-native-svg in the bare React Native install command.
@tanstack/react-native-charts requires react-native-svg >=15.15.4 <16, but the bare command installs the unqualified latest, which can resolve an incompatible major version. Use a version specifier that stays in the declared peer range, such as react-native-svg@^15.15.4, and leave Expo installs with expo install so Expo picks its compatible native version.
Suggested documentation fix
- pnpm add `@tanstack/charts` `@tanstack/react-native-charts` d3-scale react-native-svg
+ pnpm add `@tanstack/charts` `@tanstack/react-native-charts` d3-scale react-native-svg@^15.15.4📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Bare React Native 0.86 applications install the renderer directly: | |
| ```sh | |
| pnpm add @tanstack/charts @tanstack/react-native-charts d3-scale react-native-svg | |
| ``` | |
| Bare React Native 0.86 applications install the renderer directly: | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/installation.md` around lines 80 - 84, Update the bare React Native
installation command in the installation documentation to pin react-native-svg
to a version within `@tanstack/react-native-charts`’ peer range, such as ^15.15.4.
Leave the Expo installation command using expo install unchanged.
| Packed tarballs are typechecked and bundled through default bare React Native | ||
| and Expo Metro configurations on iOS and Android. The workspace Expo 57 | ||
| fixture also renders in Expo Go on an iOS simulator. Bare-native and Android | ||
| simulators, physical devices, gestures, visual parity, and screen readers are | ||
| not yet support claims. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the support-claim wording.
The sentence says are not yet support claims. Replace it with are outside the current support claims or are not currently supported. The current wording is ungrammatical and ambiguous for users.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/installation.md` around lines 96 - 100, Update the support-claim
sentence in the installation documentation to replace “are not yet support
claims” with clear wording such as “are outside the current support claims” or
“are not currently supported,” while preserving the listed platform and
capability scope.
| Bare React Native applications can install it directly: | ||
|
|
||
| ```sh | ||
| npm install react-native-svg | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
rg -n -C2 'react-native-svg|react-native@|react@|15\.15' \
packages/react-native-charts/package.json \
packages/react-native-charts/README.md \
packages/charts-core/docs/installation.mdRepository: TanStack/charts
Length of output: 4043
Bound React Native installation commands with the declared peer ranges.
@tanstack/react-native-charts declares react ^19.2.3, react-native ^0.86.0, and react-native-svg >=15.15.4 <16. Update the bare install commands and tested-version range so users do not get broader or incompatible versions.
packages/react-native-charts/README.md#L19-L23: Usenpm install react-native-svg@^15.15.4or the tested exact version.packages/charts-core/docs/installation.md#L20-L22: Usepnpm add@tanstack/react-native-chartsreact@^19.2.3 react-native@^0.86.0 react-native-svg@^15.15.4.packages/charts-core/docs/installation.md#L82-L84: Usepnpm add@tanstack/charts@tanstack/react-native-chartsd3-scale react-native-svg@^15.15.4.packages/react-native-charts/README.md#L54-L56: Replacereact-native-svg15.15.x with>=15.15.4 <16or15.15.5.
📍 Affects 2 files
packages/react-native-charts/README.md#L19-L23(this comment)packages/charts-core/docs/installation.md#L20-L22packages/charts-core/docs/installation.md#L82-L84packages/react-native-charts/README.md#L54-L56
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/react-native-charts/README.md` around lines 19 - 23, Bound all React
Native installation and tested-version references to the declared peer ranges:
in packages/react-native-charts/README.md lines 19-23 use
react-native-svg@^15.15.4 (or the tested exact version), in
packages/charts-core/docs/installation.md lines 20-22 include react@^19.2.3,
react-native@^0.86.0, and react-native-svg@^15.15.4, in
packages/charts-core/docs/installation.md lines 82-84 use
react-native-svg@^15.15.4, and in packages/react-native-charts/README.md lines
54-56 replace the 15.15.x reference with >=15.15.4 <16 or 15.15.5.
| await React.act(() => { | ||
| root.render( | ||
| <Chart | ||
| definition={definition} | ||
| accessibilityLabel="Revenue" | ||
| width={480} | ||
| height={260} | ||
| onFocusChange={onFocusChange} | ||
| />, | ||
| ) | ||
| }) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Look for the React act environment flag and the Vitest setup for the package.
set -euo pipefail
rg -n 'IS_REACT_ACT_ENVIRONMENT'
fd -t f 'vitest.config' -x cat -n {}
fd -t f 'vitest.workspace' -x cat -n {}Repository: TanStack/charts
Length of output: 153
🏁 Script executed:
#!/bin/bash
set -u
echo "== tracked files matching react-native-charts =="
git ls-files | rg 'packages/react-native-charts/.+|vitest\.config|vitest\.workspace|setup|vite\.config' || true
echo "== package files =="
for p in package.json packages/react-native-charts/package.json; do
if [ -f "$p" ]; then
echo "--- $p"
cat -n "$p"
fi
done
echo "== search act flag variants =="
rg -n --hidden --no-regex-esc 'IS_REACT_ACT_ENVIRONMENT|`@testing-library/setup`|actEnv|env\.' . || true
echo "== vitest config/workspace files =="
while IFS= read -r f; do
echo "--- $f"
cat -n "$f"
done < <(git ls-files | rg '(^|/)vitest\.(config|workspace)(\..+)?|(setup.*test|.*test.*setup)\.(js|ts|mjs|cts|mcts|jsx|tsx)$' || true)Repository: TanStack/charts
Length of output: 10617
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== react-native chart test header =="
sed -n '1,80p' packages/react-native-charts/src/Chart.test.tsx | cat -n
echo
echo "== vitest config =="
cat -n vitest.config.ts
echo
echo "== setup files =="
git ls-files | rg '(^|/)setup.*test\.|.*test.*setup\.|packages/react-native-charts/src/.+\.test\.(ts|tsx)$' | sort
for f in $(git ls-files | rg '(^|/)setup.*test\.|.*test.*setup\.|packages/react-native-charts/src/.+\.test\.(ts|tsx)$'); do
echo "--- $f"
sed -n '1,220p' "$f" | cat -n
done
echo
echo "== act flag references using grep instead of rg flagged option =="
grep -RIn 'IS_REACT_ACT_ENVIRONMENT' . || true
echo
echo "== files with act imports/usages =="
grep -RIn --include='*.ts' --include='*.tsx' --include='*.js' --include='*.mjs' '\bReact\.act\b|\bimport .*act\b' . || trueRepository: TanStack/charts
Length of output: 43356
Set the React act environment flag.
packages/react-native-charts/src/Chart.test.tsx uses React.act, but no repository setup sets globalThis.IS_REACT_ACT_ENVIRONMENT = true, and the Vitest config does not configure Testing Library setup. Add an environment setup that sets the flag for Vitest jsdom tests to avoid React act warnings.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/react-native-charts/src/Chart.test.tsx` around lines 156 - 166,
Configure the Vitest jsdom test environment to set
globalThis.IS_REACT_ACT_ENVIRONMENT to true before tests run, using the
repository’s existing Vitest setup mechanism. Ensure the setup applies to
Chart.test.tsx and other React tests without changing the React.act usage.
| React.useEffect(() => { | ||
| const previous = focusedPointsRef.current[0] | ||
| if (!focusModel || !previous) return | ||
| const restored = focusModel.restore(previous) | ||
| if (restored) { | ||
| setFocusSource('restored') | ||
| commitFocus(focusModel.group(restored)) | ||
| } else { | ||
| setPinnedKey(null) | ||
| commitFocus([]) | ||
| } | ||
| }, [commitFocus, focusModel]) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
An unmemoized definition prop can drive a render loop.
The chain is: definition identity → scene (Line 127) → focusModel (Line 131) → this effect. The effect calls focusModel.restore, which returns a point from the new scene.points. commitFocus compares by reference, so the references always differ, and it calls setFocusedPoints plus onFocusChange.
If a consumer creates definition inline and also updates parent state from onFocusChange, each focus change recreates definition, which recreates the scene and refires this effect. The result is a sustained update loop.
Add a guard so the restore path does not emit when the restored point is equivalent to the current focus, for example by comparing with samePointIdentity from ./interaction before it calls commitFocus. Also state the memoization requirement for definition in the package README.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/react-native-charts/src/Chart.tsx` around lines 172 - 183, The
restore effect around focusModel.restore must avoid emitting when the restored
point is equivalent to the current focused point: use samePointIdentity from
./interaction before calling commitFocus, while preserving the existing reset
behavior for failed restores. Update the package README to state that consumers
must memoize the definition prop.
| function scopedId(prefix: string, id: string) { | ||
| return prefix ? `${prefix}-${sanitizeId(id)}` : sanitizeId(id) | ||
| } | ||
|
|
||
| function sanitizeId(value: string) { | ||
| return value.replaceAll(/[^a-zA-Z0-9_-]/g, '') | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the public scene contract before tracing gradient producers.
ast-grep outline packages/charts-core/src/types.ts --match ChartScene --view expanded
# Find gradient construction and custom-scene extension paths.
rg -n -P -C 5 '\bgradients\s*:' packages/charts-core/src packages/react-native-charts/src
rg -n -P -C 5 '\bid\s*:\s*[^,]+' packages/charts-core/src packages/react-native-charts/src
# Demonstrate the collision without executing repository code.
node - <<'NODE'
const sanitizeId = (value) => value.replaceAll(/[^a-zA-Z0-9_-]/g, '')
for (const value of ['a.b', 'a:b', 'ab']) {
console.log(`${value} -> ${sanitizeId(value)}`)
}
NODERepository: TanStack/charts
Length of output: 50372
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate relevant type definitions =="
rg -n -C 4 'interface ChartLinearGradient|type ChartLinearGradient|id:\s*string|gradients:' packages/charts-core/src/types.ts packages/react-native-charts/src types packages -g '*.ts' -g '*.tsx' | head -200
echo
echo "== SvgScene gradient handling =="
rg -n -C 8 'scopedId|sanitizeId|gradients|linearGradient|gradientDef|fill="url|stroke="url|url\(#' packages/react-native-charts/src/SvgScene.tsx
echo
echo "== core gradient construction and paint references =="
rg -n -C 5 'gradients|linearGradient|ChartLinearGradient|url\(#|fill:|stroke:' packages/charts-core/src -g '*.ts' | sed -n '1,260p'Repository: TanStack/charts
Length of output: 12608
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== SvgScene relevant sections =="
sed -n '1,330p' packages/react-native-charts/src/SvgScene.tsx
echo
echo "== d3 svg-resources sanitization for comparison =="
sed -n '1,100p' packages/charts-core-d3/src/svg-resources.ts
echo
echo "== gradient paint references in react-native and d3 renderers =="
rg -n -C 6 'url\(#|gradient|gradientDef|ChartLinearGradient|gradients' packages/charts-core-d3/src packages/react-native-charts/src packages/charts-core/src --glob '*.ts' --glob '*.tsx' | sed -n '1,260p'
echo
echo "== TypeScript type of ChartLinearGradient =="
sed -n '390,425p' packages/charts-core/src/types.tsRepository: TanStack/charts
Length of output: 31137
Prevent sanitized SVG identifier collisions.
sanitizeId is non-injective, so different values such as a.b, a:b, and ab can produce the same SVG id. A ChartLinearGradient accepts arbitrary id strings, so collision-prone custom scenes can emit gradients that render under one shared SVG resource. Use a collision-free encoding or validate gradient ids before this renderer emits them.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/react-native-charts/src/SvgScene.tsx` around lines 270 - 276, Update
sanitizeId and the scopedId flow used by ChartLinearGradient so arbitrary custom
gradient ids remain unique after SVG-safe normalization; replace the lossy
character removal with a collision-free encoding, or validate and reject ids
that would collide before emitting resources. Preserve stable prefix handling
while ensuring distinct inputs such as a.b, a:b, and ab cannot produce the same
SVG identifier.
| vi.mock('react-native', () => ({ | ||
| Text: 'span', | ||
| View: 'div', | ||
| })) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
The react-native mock does not flatten array styles.
NativeChartTooltip passes style={[tooltipStyle, { left, top }]} at Tooltip.tsx Line 131. This mock maps View to the DOM tag 'div', so react-dom receives an array for the style prop. react-dom treats the array as a plain object and warns about the numeric keys as unsupported style properties.
Chart.test.tsx already flattens array styles in its MockView at Lines 23-25. Apply the same flattening here, so the tests do not depend on tolerated React warnings.
🧪 Proposed mock with style flattening
-vi.mock('react-native', () => ({
- Text: 'span',
- View: 'div',
-}))
+vi.mock('react-native', async () => {
+ const ReactModule = await import('react')
+ const flatten = (style: unknown) =>
+ Array.isArray(style)
+ ? Object.assign({}, ...style.filter(Boolean))
+ : style
+ return {
+ Text: 'span',
+ View: ({ style, children, ...rest }: Record<string, unknown>) =>
+ ReactModule.createElement(
+ 'div',
+ { ...rest, style: flatten(style) },
+ children as React.ReactNode,
+ ),
+ }
+})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| vi.mock('react-native', () => ({ | |
| Text: 'span', | |
| View: 'div', | |
| })) | |
| vi.mock('react-native', async () => { | |
| const ReactModule = await import('react') | |
| const flatten = (style: unknown) => | |
| Array.isArray(style) | |
| ? Object.assign({}, ...style.filter(Boolean)) | |
| : style | |
| return { | |
| Text: 'span', | |
| View: ({ style, children, ...rest }: Record<string, unknown>) => | |
| ReactModule.createElement( | |
| 'div', | |
| { ...rest, style: flatten(style) }, | |
| children as React.ReactNode, | |
| ), | |
| } | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/react-native-charts/src/Tooltip.test.ts` around lines 18 - 21,
Update the react-native mock in Tooltip.test.ts to replace the string View
mapping with a MockView component that flattens array style props before
rendering the div, matching the established MockView behavior in Chart.test.tsx.
Keep the Text mock and existing tooltip rendering behavior unchanged.
| browser: [ | ||
| 'packages/charts-core/src/adapter.ts', | ||
| 'packages/charts-core/src/adapter-renderer.ts', | ||
| 'packages/charts-core/src/canvas.ts', | ||
| 'packages/charts-core/src/dom.ts', | ||
| 'packages/charts-core/src/dom-text.ts', | ||
| 'packages/charts-core/src/export.ts', | ||
| 'packages/charts-core/src/reconcile.ts', | ||
| 'packages/charts-core/src/renderer.ts', | ||
| 'packages/charts-core/src/svg-renderer.ts', | ||
| 'packages/charts-core/src/svg-resources.ts', | ||
| 'packages/charts-core/src/svg-surface.ts', | ||
| 'packages/charts-core/src/svg.ts', | ||
| 'packages/react-charts/src/CanvasChart.tsx', | ||
| 'packages/react-charts/src/Chart.tsx', | ||
| 'packages/react-charts/src/RendererChart.tsx', | ||
| ], |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Check what the native benchmark entries import.
set -euo pipefail
fd -t f 'charts-react-native*.ts' benchmarks/entries --exec cat -n
rg -n "svg-renderer|src/svg\.ts|universal" scripts/measure-bundles.mjs scripts/measure-react-native-poc.mjsRepository: TanStack/charts
Length of output: 2342
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- measure-bundles relevant slices ---\n'
sed -n '1,90p' scripts/measure-bundles.mjs
sed -n '340,430p' scripts/measure-bundles.mjs
sed -n '960,1025p' scripts/measure-bundles.mjs
printf '\n--- measure-react-native-poc relevant slices ---\n'
sed -n '1,180p' scripts/measure-react-native-poc.mjs
printf '\n--- package entry files ---\n'
fd -t f 'package.json|universal.*|react-native-chart'|xargs -r -I{} sh -c 'echo "### {}"; sed -n "1,220p" "{}"' | sed -n '1,260p'
printf '\n--- imports / exports around charts-core svg and universal ---\n'
rg -n "svg-renderer|from ['\"]\.\/svg|export .*svg|from ['\"]@\tanstack/charts/universal|from ['\"]`@tanstack/react-native-charts`|export \{ Chart \}" packages benchmarks scripts -g '*.ts' -g '*.tsx' -g '*.mjs' -g '*.json' | sed -n '1,240p'Repository: TanStack/charts
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- measure-bundles relevant slices ---'
sed -n '1,90p' scripts/measure-bundles.mjs
sed -n '340,430p' scripts/measure-bundles.mjs
sed -n '960,1025p' scripts/measure-bundles.mjs
printf '%s\n' ''
printf '%s\n' '--- measure-react-native-poc relevant slices ---'
sed -n '1,180p' scripts/measure-react-native-poc.mjs
printf '%s\n' ''
printf '%s\n' '--- imports / exports around charts-core svg and universal ---'
rg -n "svg-renderer|from ['\"]\.\/svg|export .*svg|from ['\"]@\tanstack/charts/universal|from ['\"]`@tanstack/react-native-charts`|export \{ Chart \}" packages benchmarks scripts -g '*.ts' -g '*.tsx' -g '*.mjs' -g '*.json' | sed -n '1,240p'Repository: TanStack/charts
Length of output: 20943
Keep the native SVG boundary aligned with the universal entry boundary.
scripts/measure-react-native-poc.mjs requires packages/charts-core/src/svg-renderer.ts and packages/charts-core/src/svg.ts in the native universal bundle, but scripts/measure-bundles.mjs treats those same modules as browser. A native-boundary bundle reachable through @tanstack/charts/universal will cross the browser group and fail while still needing the static SVG serializer. Move these shared serializer modules to a neutral/native group and reject them only from a dedicated browser group.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/measure-bundles.mjs` around lines 36 - 52, Update the bundle grouping
in the configuration used by measure-bundles so charts-core/src/svg-renderer.ts
and charts-core/src/svg.ts are assigned to the neutral/native group rather than
browser. Add or use a dedicated browser-only group for rejecting
browser-exclusive modules, while preserving the universal/native boundary
required by measure-react-native-poc.mjs.
Summary
@tanstack/react-native-chartsas an experimental package with compiled ESM, declarations, provenance metadata, andreact-nativeconditional exports/tooltip@tanstack/charts/universalInstall contract
After the one-time npm bootstrap, a React Native application can install and import the adapter normally:
The tested lanes are Expo 57 / React Native 0.86.2 with
react-native-svg15.15.4 and bare React Native 0.86.2 withreact-native-svg15.15.5. The published peer range is React^19.2.3, React Native^0.86.0, andreact-native-svg>=15.15.4 <16.The packed-consumer gate installs only checked tarballs, uses each consumer's TypeScript installation, asserts Metro resolves installed
distmodules, and bundles iOS and Android through both default Metro configurations. A separate base-entry bundle proves that importing the root does not retain the optional tooltip implementation.Compatibility and support boundary
Existing browser imports and behavior are unchanged. The browser-first
@tanstack/chartsroot remains the normal web entry;/universalis the cross-runtime barrel, and granular entries remain the bundle-sensitive path.The workspace Expo 57 fixture boots in Expo Go on an iOS simulator, renders the chart, and logs Hermes bytecode execution. Packed tarballs independently install, typecheck, and compile through bare and Expo iOS/Android pipelines. This remains experimental: packed-artifact device execution, bare-native and Android simulators, physical devices, gesture arbitration, VoiceOver/TalkBack, release builds, performance, and binary-size validation are not support claims.
Bundle evidence
/universalover the equivalent granular entry: 119.06 KiB minified / 28.91 KiB gzip / 102 modules on both platformsRelease prerequisite
@tanstack/react-native-chartsis still absent from npm. After this PR merges and before the fixed 0.5.0 release publishes:react-native-charts-0.4.0.tgzonce with public access from hosted CI using a granular npm token and provenanceTanStack/chartsand.github/workflows/release.ymlas the package's trusted publisherThe pending fixed minor changeset then moves all 12 packages to 0.5.0 through the normal OIDC release path.
Validation
pnpm validate— full 16-dependency CI graph; 126 test files and 669 testspnpm benchmark:checkpnpm react-native:poc:typespnpm react-native:poc:bundle— ten production Metro bundles across iOS and Androidpnpm release:artifactsandpnpm release:check— 12 validated 0.4.0 artifactsSummary by CodeRabbit